package com.augurit.common.system.service.org.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.orm.Page;

import com.augurit.common.constant.OrgConstant;
import com.augurit.common.dao.AcFunctionDao;
import com.augurit.common.dao.AcMenuDao;
import com.augurit.common.dao.AcModuleDao;
import com.augurit.common.dao.AcRoleFuncDao;
import com.augurit.common.dao.AcUserFuncDao;
import com.augurit.common.entity.AcFunction;
import com.augurit.common.entity.AcModule;
import com.augurit.common.entity.AcUserFunc;
import com.augurit.common.syscode.service.ISysCodeService;
import com.augurit.common.syscode.web.form.SysCodeForm;
import com.augurit.common.system.convert.AcFunctionConverter;
import com.augurit.common.system.service.org.IAcFunctionService;
import com.augurit.common.system.util.OrgUtils;
import com.augurit.common.system.web.org.form.AcApplicationForm;
import com.augurit.common.system.web.org.form.AcFunctionForm;
import com.augurit.common.system.web.org.form.AcMenuForm;
import com.augurit.common.system.web.org.form.AcUserFuncForm;
import com.augurit.common.util.HqlUtils;
import com.augurit.common.util.PageUtils;

/**
 * 功能逻辑实现类
 */
@Service
@Transactional
public class AcFunctionServiceImpl implements IAcFunctionService {
	
	// DAO 引用
	@Autowired
	private AcFunctionDao acFunctionDao;
	
	@Autowired
	private AcModuleDao acModuleDao;
	
	@Autowired
	private AcRoleFuncDao acRoleFuncDao;
	
	@Autowired
	private AcUserFuncDao acUserFuncDao;
	
	@Autowired
	private AcMenuDao acMenuDao;
	
	@Autowired
	private ISysCodeService syscodeService;
	
	
	
	/**
	 * 根据ID获取功能Form对象
	 * @param funcId 功能主键ID
	 * @return 功能Form对象
	 */
	@Transactional(readOnly = true)
	public AcFunctionForm get(Long funcId){
		if(funcId != null){
			AcFunction entity = acFunctionDao.get(funcId);
			if(entity != null)
				return AcFunctionConverter.convertToForm(entity);
		}
		return null;
	}

	/**
	 * 根据ID获取完整的功能Form对象，包括父模块名称、所属应用名称、关联菜单等
	 * @param funcId 功能主键ID
	 * @param loadAppAndParentModule 是否加载所属应用名称和父模块名称
	 * @param loadMenus 是否加载关联菜单名称
	 * @param appMapBuffer web context中缓存所有应用的变量。如无缓存则可直接设为NULL
	 * @return
	 */
	@Transactional(readOnly = true)
	public AcFunctionForm getFunc(Long funcId, boolean loadAppAndParentModule, boolean loadMenus, Map<Long, AcApplicationForm> appMapBuffer){
		AcFunctionForm form = get(funcId);

		//添加功能Form对象扩展属性
		if(loadAppAndParentModule)
			loadAppAndParentModule(form, appMapBuffer);

		if(loadMenus)
			loadMenuNames(form);
		
		return form;
	}
	
	/**
	 * 加载所属应用名称和父模块名称
	 * @param form
	 * @param appMapBuffer web context中缓存所有应用的变量
	 */
	private void loadAppAndParentModule(AcFunctionForm form, Map<Long, AcApplicationForm> appMapBuffer){
		if(form != null && form.getModuleId() != null){
			AcModule module = acModuleDao.get(form.getModuleId());
			form.setModuleName(this.getModulePath(module));
			
			if(appMapBuffer != null && appMapBuffer.size() > 0){
				AcApplicationForm app = appMapBuffer.get(module.getAppId());
				form.setAppName(app != null ? app.getAppName() : "");
			}
		}
	}
	
	/**
	 * 加载所属应用名称和模块路径
	 * @param forms
	 * @param appMapBuffer web context中缓存所有应用的变量
	 */
	private void loadAppAndModulePath(List<AcFunctionForm> forms, Map<Long, AcApplicationForm> appMapBuffer){
		if(forms != null && forms.size() > 0){
			for(AcFunctionForm form : forms)
				loadAppAndParentModule(form, appMapBuffer);
		}
	}
	
	/**
	 * 加载功能对象的关联菜单名称（多个菜单名称中间用顿号隔开）
	 * @param form
	 */
	private void loadMenuNames(AcFunctionForm form){
		String menuNames = acMenuDao.getMenuNamesByFuncId(form.getFuncId());
		form.setMenuNames(menuNames);
	}
	
	/**
	 * 加载功能对象的关联菜单名称（多个菜单名称中间用顿号隔开）
	 * @param form
	 */
	private void loadMenuNames(List<AcFunctionForm> forms){
		if(forms != null && forms.size() > 0){
			for(AcFunctionForm form : forms)
				loadMenuNames(form);
		}
	}
	
    /**
     * 根据功能id数组查找对应的功能form对象列表
     * @param funcIds 功能id数组
     */
	public List<AcFunctionForm> get(Long[] funcIds){
		if(funcIds != null && funcIds.length > 0){
			List<AcFunctionForm> list = new ArrayList();
			
			for(Long funcId : funcIds)
				list.add(get(funcId));
			
			return list;
		}else
			return null;
	}
	
	/**
     * 根据功能id数组查找对应的功能form对象列表
     * @param funcIds 功能id数组
     */
	public List<AcFunctionForm> getFuncs(Long[] funcIds, Map<Long, AcApplicationForm> appMapBuffer){
		if(funcIds != null && funcIds.length > 0){
			List<AcFunctionForm> list = new ArrayList();
			
			for(Long funcId : funcIds)
				list.add(this.getFunc(funcId, true, true, appMapBuffer));
			
			return list;
		}else
			return null;
	}

	/**
	 * 保存功能Form对象数组
	 * @param forms Form对象数组
	 */
	public void save(AcFunctionForm... forms){
		if(forms != null)
			for(AcFunctionForm form : forms)
				acFunctionDao.save(form);
	}

	/**
	 * 根据主键ID集合删除多个功能对象
	 * @param ids 功能主键ID集合
	 */
	public void delete(Long... ids) {
		if(ids != null)
			acFunctionDao.delete(ids);
	}
	

	/**
	 * 级联删除功能
	 * @param funcId 功能的主键
	 */
	public void deleteFuncCascade(Long... funcIds) {
		if (funcIds != null) {
			for(Long funcId : funcIds){
				
				// 更新功能所属的模块
				Long moduleId = acFunctionDao.get(funcId).getModuleId();
				acModuleDao.updateModuleAfterRemoveChildren(moduleId);
	
				// 删除AC_ROLE_FUNC中对应的项
				acRoleFuncDao.deleteByFuncId(funcId);
	
				// 删除AC_USER_FUNC中对应的项
				acUserFuncDao.deleteByFuncId(funcId);
				
				// 清除菜单的关联项
				acMenuDao.disAssociateWithFunc(funcId);
				
				// 删除功能本身
				acFunctionDao.delete(funcId);
			}
		}
	}
	
	/**
	 * 级联添加功能Form对象
	 * @param form 功能Form对象
	 */
	public void addFuncCascade(AcFunctionForm form){
		if(form != null){
			// 更新所属模块
			Long moduleId = form.getModuleId();
			acModuleDao.updateModuleAfterAddChildren(moduleId);
			
			// 添加指定功能
			save(form);
		}
	}
	
	
	/**
	 * 根据模块的id找出所有的功能点
	 * @param moduleId 模块id
	 * @return 功能form对象列表
	 */
	@Transactional(readOnly = true)
	public List<AcFunctionForm> getFuncsByModuleId(Long moduleId){
		List<AcFunction> list = acFunctionDao.getFuncsByModuleId(moduleId);
		return AcFunctionConverter.convertToFormList(list);
	}
	
	/**
	 * 分页查询指定模块下的直属功能列表
	 * @param mouduleId 模块ID
	 * @param page 分页对象
	 * @return 包括功能form对象的分页对象
	 */
	@Transactional(readOnly = true)
	public Page<AcFunctionForm> getFuncsByModuleId(Long moduleId, Page<AcFunctionForm> page, Map<Long, AcApplicationForm> appMapBuffer, Map<String, List<SysCodeForm>> sysCodeBuffer){
		Page<AcFunction> pg = PageUtils.newPageInstance(page);
		
		// 按过滤条件分页查找对象
		String hql = "from AcFunction func where func.moduleId=?";
		List values = new ArrayList();
		values.add(moduleId);
		
		return executeQueryHql(hql, values, pg, page, appMapBuffer, sysCodeBuffer);
	}
	
	/**
	 * 分页查询功能列表
	 * @param page 分页对象
	 * @return 包括功能form对象的分页对象
	 */
	@Transactional(readOnly = true)
	public Page<AcFunctionForm> getFuncs(Page<AcFunctionForm> page, AcFunctionForm form, Map<Long, AcApplicationForm> appMapBuffer, Map<String, List<SysCodeForm>> sysCodeBuffer){
		Page<AcFunction> pg = PageUtils.newPageInstance(page);
		
		// 按过滤条件分页查找对象
		String hql = "from AcFunction func where 1=1";
		List values = new ArrayList();
		
		if(form != null){
			if(form.getFuncCode() != null && form.getFuncCode().trim().length() > 0){
				hql += " and func.funcCode like ?";
				values.add("%" + form.getFuncCode() + "%");
			}
			
			if(form.getFuncName() != null && form.getFuncName().trim().length() > 0){
				hql += " and func.funcName like ?";
				values.add("%" + form.getFuncName() + "%");
			}
		}
		
		return executeQueryHql(hql, values, pg, page, appMapBuffer, sysCodeBuffer);
	}

	/**
	 * 执行HQL查询语句，带排序、加载所属应用名称和模块路径、加载功能对象的关联菜单名称等功能
	 * @param hql
	 * @param values
	 * @param pg
	 * @param page
	 * @param appMapBuffer
	 * @param sysCodeBuffer
	 * @return
	 */
	private Page<AcFunctionForm>  executeQueryHql(String hql, List values, Page<AcFunction> pg, Page<AcFunctionForm> page,
			Map<Long, AcApplicationForm> appMapBuffer, Map<String, List<SysCodeForm>> sysCodeBuffer){
		
		// 排序
		hql += HqlUtils.buildOrderBy(page, "func");
		
		acFunctionDao.findPage(pg, hql, values);

		// 转换为Form对象列表并赋值到原分页对象中
		List<AcFunctionForm> list = AcFunctionConverter.convertToFormList(pg.getResult(),
				syscodeService.getItems(OrgConstant.SYS_CODE_FUNCTION_TYPE,  sysCodeBuffer));
		
		//加载所属应用名称和模块路径
		this.loadAppAndModulePath(list, appMapBuffer);
		
		//加载功能对象的关联菜单名称
		this.loadMenuNames(list);
		
		PageUtils.copy(pg, list, page);
		return page;
	}
	
	/**
	 * 找出指定模块下的所有的功能点
	 * @param moduleId 模块主键
	 * @return 指定模块下所有功能点的列表
	 */
	public List<Long> getFuncIdsByModuleId(Long moduleId){
		return acFunctionDao.getFuncIdsByModuleId(moduleId);
	}
	
	/**
	 * 找出模块列表下直属模块的集合列表
	 * @param moduleIds 模块主键数组
	 * @return 模块列表下直属模块的集合列表
	 */
	public List<AcFunctionForm> getFuncsByModuleIds(Long[] moduleIds) {
		return AcFunctionConverter.convertToFormList(
				acFunctionDao.getFuncsByModuleIds(moduleIds));
	}

	/**
	 * 获取指定功能的模块ID
	 * @param funcId 功能ID
	 * @return 所属模块ID
	 */
	public Long getModuleId(Long funcId){
		if(funcId != null){
			AcFunction entity = acFunctionDao.get(funcId);
			if(entity != null)
				return entity.getModuleId();
		}
		return null;
	}
	
	/**
	 * 获取用户特别开通的功能
	 * @param userId 用户ID
	 */
	public List<AcFunctionForm> getPermittedFuncsByUserId(Long userId, Map<Long, AcApplicationForm> appMapBuffer){
		if(userId != null){
			Long[] funcIds = acUserFuncDao.getPermittedFuncIdsByUserId(userId);
			return this.getFuncs(funcIds, appMapBuffer);
		}
		return null;
	}
	
	/**
	 * 获取用户特别开通的功能ID集合
	 * @param userId 用户ID
	 * @return  功能ID集合
	 */
	public Long[] getPermittedFuncIdsByUserId(Long userId){
		if(userId != null){
			return acUserFuncDao.getPermittedFuncIdsByUserId(userId);
		}
		return null;
	}
	
	
	/**
	 * 获取被特别开通某项功能的用户id数组
	 * @param funcId 功能id
	 * @return 用户id数组
	 */
	public Long[] getUserIdsByOpenedFuncId(Long funcId){
		if( funcId != null){
			return acUserFuncDao.getUserIdsBySpcialOpenFuncId(funcId);
		}
		return null;
	}
	
	/**
	 * 获取被特别禁止某项功能的用户id数组
	 * @param funcId 功能id
	 * @return 用户id数组
	 */  
	public Long[] getUserIdsByForbidenFuncId(Long funcId){
		if( funcId != null){
			return acUserFuncDao.getUserIdsBySpcialFibidenFuncId(funcId);
		}
		return null;
	}
	
	/**
	 * 获取用户特别禁止的功能form列表
	 * @param userId 用户ID
	 * @return
	 */
	public List<AcFunctionForm> getForbidenFuncsByUserId(Long userId, Map<Long, AcApplicationForm> appMapBuffer){
		if(userId != null){
			Long[] funcIds = acUserFuncDao.getForbidenFuncIdsByUserId(userId);
			return this.getFuncs(funcIds, appMapBuffer);
		}
		return null;
	}
	
	/**
	 * 获取用户特别禁止的功能ID集合
	 * @param userId 用户ID
	 * @return  功能ID集合
	 */
	public Long[] getForbidenFuncIdsByUserId(Long userId){
		if(userId != null)
			return acUserFuncDao.getForbidenFuncIdsByUserId(userId);
		else
			return null;
	}
	
	/**
	 * 移动指定功能到指定模块
	 * @param funcId 功能id
	 * @param destinationModuleId 目标模块id
	 */
	public void moveFuncToOtherModule(Long funcId,Long destinationModuleId){
		if(funcId != null && destinationModuleId != null){
			AcFunction entity = acFunctionDao.get(funcId);
			Long oldModuleId = entity.getModuleId();
			entity.setModuleId(destinationModuleId);
			acFunctionDao.save(entity);
			acModuleDao.updateModuleAfterAddChildren(destinationModuleId);
			acModuleDao.updateModuleAfterRemoveChildren(oldModuleId);
			
		}
	}
	
	/**
	 * 将功能设置为特别禁止
	 *@author 舒军
	 *@param funcIds 功能id数组
	 *@param userId 用户id
	 * */
	public void setForbiddenFunsForUser(Long[] funcIds,Long userId){
		if(funcIds != null && funcIds.length>0 && userId != null){
			setFunsForUser(userId,OrgConstant.ZERO, funcIds);
		}
	}
	
	/**
	 * 为某一批用户设置某项特别禁止功能
	 * @param userIds 用户id数组
	 * @param funcId 功能id
	 */
	public void setForbiddenFunForUsers(Long[] userIds, Long funcId){
		if(funcId != null && userIds != null && userIds.length>0){
			for(Long userId:userIds)
				setFunsForUser(userId, OrgConstant.ZERO, funcId);
		}
	}
	
	/**
	 * 将功能设置为特别开通/禁止
	 *@author 舒军
	 *@param funcIds 功能id数组
	 *@param userId 用户id
	 *@param authType 开通/禁止的类型
	 * */
	private void setFunsForUser(Long userId, String authType, Long... funcIds) {
		if(funcIds != null && funcIds.length > 0 && userId != null && authType != null) {
			for(Long funcId : funcIds) {
				AcUserFunc entity = this.getUserFuncByBothId(funcId, userId);
				// 判断是否存在
				if (entity != null) {
					// 存在相同的
					if(entity.getAuthType().equals(authType))
						continue;
					// 存在对立的,修改
					else if (entity.getAuthType().equals(OrgConstant.ONE))
						entity.setAuthType(OrgConstant.ZERO);
					else
						entity.setAuthType(OrgConstant.ONE);
					
					AcUserFuncForm form = AcFunctionConverter.convertToForm(entity);
					this.acUserFuncDao.save(form);
				} else
					saveUF(funcId, userId, authType);
			}
		}
	}
	
	private void saveUF(Long funcId,Long userId,String authType){
		if(funcId != null && userId != null && authType != null){
			AcFunctionForm funcForm= this.get(funcId);
			Long moduleId = funcForm.getModuleId();
			AcModule module= this.acModuleDao.get(moduleId);
			Long appId = module.getAppId();
			
			AcUserFuncForm form = new AcUserFuncForm();
			form.setFuncId(funcId);
			form.setAuthType(authType);
			form.setUserId(userId);
			form.setAppId(appId);
			form.setModuleId(moduleId);
			this.acUserFuncDao.save(form);
		}
	}
	
	private AcUserFunc getUserFuncByBothId(Long funcId,Long userId){
		AcUserFunc entity = null;
		if(funcId != null && userId != null){
			String hql="from AcUserFunc ps where ps.funcId=? and userId =?";
			List<Long> values = new ArrayList<Long>();
			values.add(funcId);
			values.add(userId);
			
			List<AcUserFunc> list = acUserFuncDao.find(hql,values);
			if(list != null && list.size() >0)
				entity =list.get(0);
		}
		return entity;
	}
	
	/**
	 * 将功能设置为特别开通
	 * @author 舒军
	 * @param funcIds 功能id数组
	 * @param userId 用户id
	 **/
	public void setOpenedFunsForUser(Long[] funcIds,Long userId){
		if(funcIds != null && funcIds.length>0 && userId != null){
			setFunsForUser(userId,OrgConstant.ONE, funcIds);
		}
	}
	
	/**
	 * 为某一批用户设置某项特别开通功能
	 * @param userIds 用户id数组
	 * @param funcId 功能id
	 */
	public void setOpenedFunForUsers(Long[] userIds, Long funcId){
		if(funcId != null && userIds != null && userIds.length > 0){
			for(Long userId: userIds){
				setFunsForUser(userId,OrgConstant.ONE, funcId);
			}
		}
	}
	
	/**
	 * 设置功能菜单名称
	 * @param funcs 功能form列表
 	 */
	public void loadMenuNamesOfFunc(List<AcFunctionForm> funcs){
		
		if(funcs != null && funcs.size() > 0){
			List<AcMenuForm> menus = acMenuDao.getRelatedMenusByFuncIds(OrgUtils.getFuncIds(funcs));
			
			for(AcFunctionForm func : funcs){
				List<String> menuNameList = OrgUtils.getMenuNamesByFuncId(func.getFuncId(), menus);
				func.setFuncName(func.getFuncName() + OrgUtils.convertToMenuNamesStr(menuNameList));
			}
		}
	}
	
	/**
	 * 根据模块ID获取模块的完整模块路径，如“/test/test1/test11”
	 * @param moduleId
	 * @return
	 */
	private String getModulePath(AcModule entity){
		String result = "";
		
		if(entity != null){
			String[] moduleIds = OrgUtils.splitSeqToArray(entity.getModuleSeq());
			
			if(moduleIds != null && moduleIds.length > 0){
				for(String id : moduleIds){
					result += OrgConstant.STRING_SEPARATOR_MODULEPATH + acModuleDao.get(Long.valueOf(id)).getModuleName();
				}
			}
		}
		
		return result;
	}
}
